transactions table: Store hash as BYTEA#495
transactions table: Store hash as BYTEA#495aditya1702 wants to merge 16 commits intoaccountid-bytea-txnsfrom
transactions table: Store hash as BYTEA#495Conversation
Implements Scan, Value, and String methods following the AddressBytea pattern. Stores 32-byte raw SHA-256 hash in database, represents as 64-character hex string in Go.
Changes the Hash field from string to HashBytea for automatic BYTEA serialization/deserialization in the database.
Converts the ingest transaction hash to HashBytea type for proper database serialization.
Converts HashBytea to string for use as map key since HashBytea is not directly comparable as a map key type.
- GetByHash: Convert input hash string to HashBytea for query - BatchInsert: Convert hashes to [][]byte, use bytea[] in SQL, return hex-encoded hashes - BatchCopy: Convert hash to bytes using Hash.Value()
Stores 32-byte raw SHA-256 hash instead of 64-char hex string, reducing storage by ~50%.
Tests for Scan, Value, Roundtrip, and String methods following the same pattern as AddressBytea tests.
All test files now use valid hex strings that can be converted to 32-byte BYTEA values instead of simple strings like "tx1", "tx2".
hash as BYTEAtransactions table: Store hash as BYTEA
There was a problem hiding this comment.
Pull request overview
This PR updates the codebase to store transactions.hash as BYTEA (raw 32 bytes) in Postgres while keeping the Go/GraphQL-facing representation as a 64-char hex string.
Changes:
- Introduces
types.HashByteawithsql.Scanner/driver.Valuerimplementations and updatestypes.Transaction.Hashto use it. - Updates transaction ingestion and data-layer inserts/queries to bind hashes as
BYTEA/bytea[](plus corresponding test updates). - Updates GraphQL schema/resolvers so
Transaction.hashcontinues to resolve as aStringdespite the underlying Go type change.
Reviewed changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/db/migrations/2025-06-10.2-transactions.sql | Changes transactions.hash column type to BYTEA in the migration script. |
| internal/indexer/types/types.go | Adds HashBytea and switches Transaction.Hash to HashBytea. |
| internal/indexer/types/types_test.go | Adds unit tests for HashBytea Scan/Value/roundtrip/String. |
| internal/indexer/processors/utils.go | Converts ingested transaction hashes to types.HashBytea. |
| internal/indexer/indexer_buffer.go | Adjusts buffer keying to use transaction.Hash.String(). |
| internal/indexer/indexer_buffer_test.go | Updates buffer tests to use valid 64-char hex hashes. |
| internal/data/transactions.go | Updates GetByHash, BatchInsert, and BatchCopy to bind hash as BYTEA. |
| internal/data/transactions_test.go | Updates transaction model tests to use valid hex hashes and HashBytea comparisons. |
| internal/data/statechanges.go | Updates tx-hash filtering to bind as types.HashBytea. |
| internal/data/statechanges_test.go | Updates state change tests/fixtures to insert/query BYTEA hashes. |
| internal/data/operations_test.go | Updates operation tests/fixtures to insert BYTEA hashes. |
| internal/data/accounts_test.go | Updates account tests/fixtures to insert BYTEA hashes. |
| internal/services/ingest_test.go | Updates ingest tests to use hex hashes and bind hash params as HashBytea/[]byte. |
| internal/serve/graphql/schema/transaction.graphqls | Forces resolver for Transaction.hash to keep GraphQL type String!. |
| internal/serve/graphql/resolvers/transaction.resolvers.go | Adds Hash() field resolver returning obj.Hash.String(). |
| internal/serve/graphql/generated/generated.go | Regenerates gqlgen output to route hash through the new resolver. |
| internal/serve/graphql/resolvers/test_utils.go | Updates GraphQL test DB setup to insert types.HashBytea hashes and adds shared hash constants. |
| internal/serve/graphql/resolvers/*_test.go | Updates GraphQL resolver tests to compare/use hex hashes via .String(). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
|
||
| for i, t := range txs { | ||
| hashes[i] = t.Hash | ||
| hashBytes, err := t.Hash.Value() |
There was a problem hiding this comment.
if Hash is empty, the type assertion below will panic. I see that this isn't possible today because the call site(ConvertTransaction) always populates hash but we can be more defensive here against future changes.
| if txHash != nil { | ||
| queryBuilder.WriteString(fmt.Sprintf(" AND to_id = (SELECT to_id FROM transactions WHERE hash = $%d)", argIndex)) | ||
| args = append(args, *txHash) | ||
| args = append(args, types.HashBytea(*txHash)) |
There was a problem hiding this comment.
With the column type change from TEXT to BYTEA, invalid hex strings passed as transactionHash from the GraphQL API now produce a driver-level error (from HashBytea.Value()) instead of silently returning empty results. Consider adding input validation at the GraphQL/resolver layer before this reaches the DB.
What
This PR updates the codebase to store transactions.hash as BYTEA (raw 32 bytes) in Postgres while keeping the Go/GraphQL-facing representation as a 64-char hex string.
Changes:
Introduces types.HashBytea with sql.Scanner/driver.Valuer implementations and updates types.Transaction.Hash to use it.
Updates transaction ingestion and data-layer inserts/queries to bind hashes as BYTEA/bytea[] (plus corresponding test updates).
Updates GraphQL schema/resolvers so Transaction.hash continues to resolve as a String despite the underlying Go type change.
Why
Storage optimization
Known limitations
N/A
Issue that this PR addresses
Closes #494